Rubberstamped by Eric Seidel.
[WebKit.git] / Tools / Scripts / webkitdirs.pm
1 # Copyright (C) 2005, 2006, 2007, 2010 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 warnings;
33 use Config;
34 use FindBin;
35 use File::Basename;
36 use File::Path;
37 use File::Spec;
38 use POSIX;
39 use VCSUtils;
40
41 BEGIN {
42    use Exporter   ();
43    our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
44    $VERSION     = 1.00;
45    @ISA         = qw(Exporter);
46    @EXPORT      = qw(&chdirWebKit &baseProductDir &productDir &XcodeOptions &XcodeOptionString &XcodeOptionStringNoConfig &passedConfiguration &setConfiguration &safariPath &checkFrameworks &currentSVNRevision);
47    %EXPORT_TAGS = ( );
48    @EXPORT_OK   = ();
49 }
50
51 our @EXPORT_OK;
52
53 my $architecture;
54 my $numberOfCPUs;
55 my $baseProductDir;
56 my @baseProductDirOption;
57 my $configuration;
58 my $configurationForVisualStudio;
59 my $configurationProductDir;
60 my $sourceDir;
61 my $currentSVNRevision;
62 my $osXVersion;
63 my $generateDsym;
64 my $isQt;
65 my $qmakebin = "qmake"; # Allow override of the qmake binary from $PATH
66 my $isSymbian;
67 my %qtFeatureDefaults;
68 my $isGtk;
69 my $isWinCE;
70 my $isWinCairo;
71 my $isWx;
72 my $isEfl;
73 my @wxArgs;
74 my $isChromium;
75 my $isInspectorFrontend;
76 my $isWK2;
77
78 # Variables for Win32 support
79 my $vcBuildPath;
80 my $windowsSourceDir;
81 my $winVersion;
82 my $willUseVCExpressWhenBuilding = 0;
83
84 # Defined in VCSUtils.
85 sub exitStatus($);
86
87 sub determineSourceDir
88 {
89     return if $sourceDir;
90     $sourceDir = $FindBin::Bin;
91     $sourceDir =~ s|/+$||; # Remove trailing '/' as we would die later
92
93     # walks up path checking each directory to see if it is the main WebKit project dir, 
94     # defined by containing Sources, WebCore, and WebKit
95     until ((-d "$sourceDir/Source" && -d "$sourceDir/Source/WebCore" && -d "$sourceDir/Source/WebKit") || (-d "$sourceDir/Internal" && -d "$sourceDir/OpenSource"))
96     {
97         if ($sourceDir !~ s|/[^/]+$||) {
98             die "Could not find top level webkit directory above source directory using FindBin.\n";
99         }
100     }
101
102     $sourceDir = "$sourceDir/OpenSource" if -d "$sourceDir/OpenSource";
103 }
104
105 sub currentPerlPath()
106 {
107     my $thisPerl = $^X;
108     if ($^O ne 'VMS') {
109         $thisPerl .= $Config{_exe} unless $thisPerl =~ m/$Config{_exe}$/i;
110     }
111     return $thisPerl;
112 }
113
114 sub setQmakeBinaryPath($)
115 {
116     ($qmakebin) = @_;
117 }
118
119 # used for scripts which are stored in a non-standard location
120 sub setSourceDir($)
121 {
122     ($sourceDir) = @_;
123 }
124
125 sub determineBaseProductDir
126 {
127     return if defined $baseProductDir;
128     determineSourceDir();
129
130     $baseProductDir = $ENV{"WEBKITOUTPUTDIR"};
131
132     if (!defined($baseProductDir) and isAppleMacWebKit()) {
133         # Silently remove ~/Library/Preferences/xcodebuild.plist which can
134         # cause build failure. The presence of
135         # ~/Library/Preferences/xcodebuild.plist can prevent xcodebuild from
136         # respecting global settings such as a custom build products directory
137         # (<rdar://problem/5585899>).
138         my $personalPlistFile = $ENV{HOME} . "/Library/Preferences/xcodebuild.plist";
139         if (-e $personalPlistFile) {
140             unlink($personalPlistFile) || die "Could not delete $personalPlistFile: $!";
141         }
142
143         my $xcodebuildVersionOutput = `xcodebuild -version`;
144         my $xcodeVersion = ($xcodebuildVersionOutput =~ /Xcode ([0-9](\.[0-9]+)*)/) ? $1 : undef;
145         my $xcodeDefaultsDomain = (eval "v$xcodeVersion" lt v4) ? "com.apple.Xcode" : "com.apple.dt.Xcode";
146         my $xcodeDefaultsPrefix = (eval "v$xcodeVersion" lt v4) ? "PBX" : "IDE";
147
148         open PRODUCT, "defaults read $xcodeDefaultsDomain ${xcodeDefaultsPrefix}ApplicationwideBuildSettings 2> " . File::Spec->devnull() . " |" or die;
149         $baseProductDir = join '', <PRODUCT>;
150         close PRODUCT;
151
152         $baseProductDir = $1 if $baseProductDir =~ /SYMROOT\s*=\s*\"(.*?)\";/s;
153         undef $baseProductDir unless $baseProductDir =~ /^\//;
154     } elsif (isSymbian()) {
155         # Shadow builds are not supported on Symbian
156         $baseProductDir = $sourceDir;
157     }
158
159     if (!defined($baseProductDir)) { # Port-spesific checks failed, use default
160         $baseProductDir = "$sourceDir/WebKitBuild";
161     }
162
163     if (isGit() && isGitBranchBuild()) {
164         my $branch = gitBranch();
165         $baseProductDir = "$baseProductDir/$branch";
166     }
167
168     if (isAppleMacWebKit()) {
169         $baseProductDir =~ s|^\Q$(SRCROOT)/..\E$|$sourceDir|;
170         $baseProductDir =~ s|^\Q$(SRCROOT)/../|$sourceDir/|;
171         $baseProductDir =~ s|^~/|$ENV{HOME}/|;
172         die "Can't handle Xcode product directory with a ~ in it.\n" if $baseProductDir =~ /~/;
173         die "Can't handle Xcode product directory with a variable in it.\n" if $baseProductDir =~ /\$/;
174         @baseProductDirOption = ("SYMROOT=$baseProductDir", "OBJROOT=$baseProductDir");
175     }
176
177     if (isCygwin()) {
178         my $dosBuildPath = `cygpath --windows \"$baseProductDir\"`;
179         chomp $dosBuildPath;
180         $ENV{"WEBKITOUTPUTDIR"} = $dosBuildPath;
181         my $unixBuildPath = `cygpath --unix \"$baseProductDir\"`;
182         chomp $unixBuildPath;
183         $baseProductDir = $unixBuildPath;
184     }
185 }
186
187 sub setBaseProductDir($)
188 {
189     ($baseProductDir) = @_;
190 }
191
192 sub determineConfiguration
193 {
194     return if defined $configuration;
195     determineBaseProductDir();
196     if (open CONFIGURATION, "$baseProductDir/Configuration") {
197         $configuration = <CONFIGURATION>;
198         close CONFIGURATION;
199     }
200     if ($configuration) {
201         chomp $configuration;
202         # compatibility for people who have old Configuration files
203         $configuration = "Release" if $configuration eq "Deployment";
204         $configuration = "Debug" if $configuration eq "Development";
205     } else {
206         $configuration = "Release";
207     }
208
209     if ($configuration && isWinCairo()) {
210         $configuration .= "_Cairo_CFLite";
211     }
212 }
213
214 sub determineArchitecture
215 {
216     return if defined $architecture;
217     # make sure $architecture is defined for non-apple-mac builds
218     $architecture = "";
219     return unless isAppleMacWebKit();
220
221     determineBaseProductDir();
222     if (open ARCHITECTURE, "$baseProductDir/Architecture") {
223         $architecture = <ARCHITECTURE>;
224         close ARCHITECTURE;
225     }
226     if ($architecture) {
227         chomp $architecture;
228     } else {
229         if (isTiger() or isLeopard()) {
230             $architecture = `arch`;
231         } else {
232             my $supports64Bit = `sysctl -n hw.optional.x86_64`;
233             chomp $supports64Bit;
234             $architecture = $supports64Bit ? 'x86_64' : `arch`;
235         }
236         chomp $architecture;
237     }
238 }
239
240 sub determineNumberOfCPUs
241 {
242     return if defined $numberOfCPUs;
243     if (isLinux()) {
244         # First try the nproc utility, if it exists. If we get no
245         # results fall back to just interpretting /proc directly.
246         chomp($numberOfCPUs = `nproc 2> /dev/null`);
247         if ($numberOfCPUs eq "") {
248             $numberOfCPUs = (grep /processor/, `cat /proc/cpuinfo`);
249         }
250     } elsif (isWindows() || isCygwin()) {
251         if (defined($ENV{NUMBER_OF_PROCESSORS})) {
252             $numberOfCPUs = $ENV{NUMBER_OF_PROCESSORS};
253         } else {
254             # Assumes cygwin
255             $numberOfCPUs = `ls /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor | wc -w`;
256         }
257     } elsif (isDarwin()) {
258         $numberOfCPUs = `sysctl -n hw.ncpu`;
259     }
260 }
261
262 sub jscPath($)
263 {
264     my ($productDir) = @_;
265     my $jscName = "jsc";
266     $jscName .= "_debug"  if configurationForVisualStudio() eq "Debug_All";
267     $jscName .= ".exe" if (isWindows() || isCygwin());
268     return "$productDir/$jscName" if -e "$productDir/$jscName";
269     return "$productDir/JavaScriptCore.framework/Resources/$jscName";
270 }
271
272 sub argumentsForConfiguration()
273 {
274     determineConfiguration();
275     determineArchitecture();
276
277     my @args = ();
278     push(@args, '--debug') if $configuration eq "Debug";
279     push(@args, '--release') if $configuration eq "Release";
280     push(@args, '--32-bit') if $architecture ne "x86_64";
281     push(@args, '--qt') if isQt();
282     push(@args, '--symbian') if isSymbian();
283     push(@args, '--gtk') if isGtk();
284     push(@args, '--efl') if isEfl();
285     push(@args, '--wince') if isWinCE();
286     push(@args, '--wx') if isWx();
287     push(@args, '--chromium') if isChromium();
288     push(@args, '--inspector-frontend') if isInspectorFrontend();
289     return @args;
290 }
291
292 sub determineConfigurationForVisualStudio
293 {
294     return if defined $configurationForVisualStudio;
295     determineConfiguration();
296     # FIXME: We should detect when Debug_All or Production has been chosen.
297     $configurationForVisualStudio = $configuration;
298 }
299
300 sub usesPerConfigurationBuildDirectory
301 {
302     # [Gtk][Efl] We don't have Release/Debug configurations in straight
303     # autotool builds (non build-webkit). In this case and if
304     # WEBKITOUTPUTDIR exist, use that as our configuration dir. This will
305     # allows us to run run-webkit-tests without using build-webkit.
306     #
307     # Symbian builds do not have Release/Debug configurations either.
308     return ($ENV{"WEBKITOUTPUTDIR"} && (isGtk() || isEfl())) || isSymbian() || isAppleWinWebKit();
309 }
310
311 sub determineConfigurationProductDir
312 {
313     return if defined $configurationProductDir;
314     determineBaseProductDir();
315     determineConfiguration();
316     if (isAppleWinWebKit() && !isWx()) {
317         $configurationProductDir = File::Spec->catdir($baseProductDir, configurationForVisualStudio(), "bin");
318     } else {
319         if (usesPerConfigurationBuildDirectory()) {
320             $configurationProductDir = "$baseProductDir";
321         } else {
322             $configurationProductDir = "$baseProductDir/$configuration";
323         }
324     }
325 }
326
327 sub setConfigurationProductDir($)
328 {
329     ($configurationProductDir) = @_;
330 }
331
332 sub determineCurrentSVNRevision
333 {
334     return if defined $currentSVNRevision;
335     determineSourceDir();
336     $currentSVNRevision = svnRevisionForDirectory($sourceDir);
337     return $currentSVNRevision;
338 }
339
340
341 sub chdirWebKit
342 {
343     determineSourceDir();
344     chdir $sourceDir or die;
345 }
346
347 sub baseProductDir
348 {
349     determineBaseProductDir();
350     return $baseProductDir;
351 }
352
353 sub sourceDir
354 {
355     determineSourceDir();
356     return $sourceDir;
357 }
358
359 sub productDir
360 {
361     determineConfigurationProductDir();
362     return $configurationProductDir;
363 }
364
365 sub jscProductDir
366 {
367     my $productDir = productDir();
368     $productDir .= "/JavaScriptCore" if isQt();
369     $productDir .= "/$configuration" if (isQt() && isWindows());
370     $productDir .= "/Programs" if (isGtk() || isEfl());
371
372     return $productDir;
373 }
374
375 sub configuration()
376 {
377     determineConfiguration();
378     return $configuration;
379 }
380
381 sub configurationForVisualStudio()
382 {
383     determineConfigurationForVisualStudio();
384     return $configurationForVisualStudio;
385 }
386
387 sub currentSVNRevision
388 {
389     determineCurrentSVNRevision();
390     return $currentSVNRevision;
391 }
392
393 sub generateDsym()
394 {
395     determineGenerateDsym();
396     return $generateDsym;
397 }
398
399 sub determineGenerateDsym()
400 {
401     return if defined($generateDsym);
402     $generateDsym = checkForArgumentAndRemoveFromARGV("--dsym");
403 }
404
405 sub argumentsForXcode()
406 {
407     my @args = ();
408     push @args, "DEBUG_INFORMATION_FORMAT=dwarf-with-dsym" if generateDsym();
409     return @args;
410 }
411
412 sub XcodeOptions
413 {
414     determineBaseProductDir();
415     determineConfiguration();
416     determineArchitecture();
417     return (@baseProductDirOption, "-configuration", $configuration, "ARCHS=$architecture", argumentsForXcode());
418 }
419
420 sub XcodeOptionString
421 {
422     return join " ", XcodeOptions();
423 }
424
425 sub XcodeOptionStringNoConfig
426 {
427     return join " ", @baseProductDirOption;
428 }
429
430 sub XcodeCoverageSupportOptions()
431 {
432     my @coverageSupportOptions = ();
433     push @coverageSupportOptions, "GCC_GENERATE_TEST_COVERAGE_FILES=YES";
434     push @coverageSupportOptions, "GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES";
435     push @coverageSupportOptions, "EXTRA_LINK= \$(EXTRA_LINK) -ftest-coverage -fprofile-arcs";
436     push @coverageSupportOptions, "OTHER_CFLAGS= \$(OTHER_CFLAGS) -DCOVERAGE -MD";
437     push @coverageSupportOptions, "OTHER_LDFLAGS=\$(OTHER_LDFLAGS) -ftest-coverage -fprofile-arcs -lgcov";
438     return @coverageSupportOptions;
439 }
440
441 my $passedConfiguration;
442 my $searchedForPassedConfiguration;
443 sub determinePassedConfiguration
444 {
445     return if $searchedForPassedConfiguration;
446     $searchedForPassedConfiguration = 1;
447
448     for my $i (0 .. $#ARGV) {
449         my $opt = $ARGV[$i];
450         if ($opt =~ /^--debug$/i || $opt =~ /^--devel/i) {
451             splice(@ARGV, $i, 1);
452             $passedConfiguration = "Debug";
453             $passedConfiguration .= "_Cairo_CFLite" if (isWinCairo() && isCygwin());
454             return;
455         }
456         if ($opt =~ /^--release$/i || $opt =~ /^--deploy/i) {
457             splice(@ARGV, $i, 1);
458             $passedConfiguration = "Release";
459             $passedConfiguration .= "_Cairo_CFLite" if (isWinCairo() && isCygwin());
460             return;
461         }
462         if ($opt =~ /^--profil(e|ing)$/i) {
463             splice(@ARGV, $i, 1);
464             $passedConfiguration = "Profiling";
465             $passedConfiguration .= "_Cairo_CFLite" if (isWinCairo() && isCygwin());
466             return;
467         }
468     }
469     $passedConfiguration = undef;
470 }
471
472 sub passedConfiguration
473 {
474     determinePassedConfiguration();
475     return $passedConfiguration;
476 }
477
478 sub setConfiguration
479 {
480     setArchitecture();
481
482     if (my $config = shift @_) {
483         $configuration = $config;
484         return;
485     }
486
487     determinePassedConfiguration();
488     $configuration = $passedConfiguration if $passedConfiguration;
489 }
490
491
492 my $passedArchitecture;
493 my $searchedForPassedArchitecture;
494 sub determinePassedArchitecture
495 {
496     return if $searchedForPassedArchitecture;
497     $searchedForPassedArchitecture = 1;
498
499     for my $i (0 .. $#ARGV) {
500         my $opt = $ARGV[$i];
501         if ($opt =~ /^--32-bit$/i) {
502             splice(@ARGV, $i, 1);
503             if (isAppleMacWebKit() || isWx()) {
504                 $passedArchitecture = `arch`;
505                 chomp $passedArchitecture;
506             }
507             return;
508         }
509     }
510     $passedArchitecture = undef;
511 }
512
513 sub passedArchitecture
514 {
515     determinePassedArchitecture();
516     return $passedArchitecture;
517 }
518
519 sub architecture()
520 {
521     determineArchitecture();
522     return $architecture;
523 }
524
525 sub numberOfCPUs()
526 {
527     determineNumberOfCPUs();
528     return $numberOfCPUs;
529 }
530
531 sub setArchitecture
532 {
533     if (my $arch = shift @_) {
534         $architecture = $arch;
535         return;
536     }
537
538     determinePassedArchitecture();
539     $architecture = $passedArchitecture if $passedArchitecture;
540 }
541
542
543 sub safariPathFromSafariBundle
544 {
545     my ($safariBundle) = @_;
546
547     return "$safariBundle/Contents/MacOS/Safari" if isAppleMacWebKit();
548     return $safariBundle if isAppleWinWebKit();
549 }
550
551 sub installedSafariPath
552 {
553     my $safariBundle;
554
555     if (isAppleMacWebKit()) {
556         $safariBundle = "/Applications/Safari.app";
557     } elsif (isAppleWinWebKit()) {
558         $safariBundle = `"$configurationProductDir/FindSafari.exe"`;
559         $safariBundle =~ s/[\r\n]+$//;
560         $safariBundle = `cygpath -u '$safariBundle'` if isCygwin();
561         $safariBundle =~ s/[\r\n]+$//;
562         $safariBundle .= "Safari.exe";
563     }
564
565     return safariPathFromSafariBundle($safariBundle);
566 }
567
568 # Locate Safari.
569 sub safariPath
570 {
571     # Use WEBKIT_SAFARI environment variable if present.
572     my $safariBundle = $ENV{WEBKIT_SAFARI};
573     if (!$safariBundle) {
574         determineConfigurationProductDir();
575         # Use Safari.app in product directory if present (good for Safari development team).
576         if (isAppleMacWebKit() && -d "$configurationProductDir/Safari.app") {
577             $safariBundle = "$configurationProductDir/Safari.app";
578         } elsif (isAppleWinWebKit()) {
579             my $path = "$configurationProductDir/Safari.exe";
580             my $debugPath = "$configurationProductDir/Safari_debug.exe";
581
582             if (configurationForVisualStudio() eq "Debug_All" && -x $debugPath) {
583                 $safariBundle = $debugPath;
584             } elsif (-x $path) {
585                 $safariBundle = $path;
586             }
587         }
588         if (!$safariBundle) {
589             return installedSafariPath();
590         }
591     }
592     my $safariPath = safariPathFromSafariBundle($safariBundle);
593     die "Can't find executable at $safariPath.\n" if isAppleMacWebKit() && !-x $safariPath;
594     return $safariPath;
595 }
596
597 sub builtDylibPathForName
598 {
599     my $libraryName = shift;
600     determineConfigurationProductDir();
601     if (isChromium()) {
602         return "$configurationProductDir/$libraryName";
603     }
604     if (isQt()) {
605         $libraryName = "QtWebKit";
606         if (isDarwin() and -d "$configurationProductDir/lib/$libraryName.framework") {
607             return "$configurationProductDir/lib/$libraryName.framework/$libraryName";
608         } elsif (isDarwin() and -d "$configurationProductDir/lib") {
609             return "$configurationProductDir/lib/lib$libraryName.dylib";
610         } elsif (isWindows()) {
611             if (configuration() eq "Debug") {
612                 # On Windows, there is a "d" suffix to the library name. See <http://trac.webkit.org/changeset/53924/>.
613                 $libraryName .= "d";
614             }
615
616             my $mkspec = `$qmakebin -query QMAKE_MKSPECS`;
617             $mkspec =~ s/[\n|\r]$//g;
618             my $qtMajorVersion = retrieveQMakespecVar("$mkspec/qconfig.pri", "QT_MAJOR_VERSION");
619             if (not $qtMajorVersion) {
620                 $qtMajorVersion = "";
621             }
622             return "$configurationProductDir/lib/$libraryName$qtMajorVersion.dll";
623         } else {
624             return "$configurationProductDir/lib/lib$libraryName.so";
625         }
626     }
627     if (isWx()) {
628         return "$configurationProductDir/libwxwebkit.dylib";
629     }
630     if (isGtk()) {
631         my $libraryDir = "$configurationProductDir/.libs/";
632         my $extension = isDarwin() ? "dylib" : "so";
633         if (-e $libraryDir . "libwebkitgtk-3.0.$extension") {
634             return $libraryDir . "libwebkitgtk-3.0.$extension";
635         }
636         return $libraryDir . "libwebkitgtk-1.0.$extension";
637     }
638     if (isEfl()) {
639         return "$configurationProductDir/$libraryName/../WebKit/libewebkit.so";
640     }
641     if (isWinCE()) {
642         return "$configurationProductDir/$libraryName";
643     }
644     if (isAppleMacWebKit()) {
645         return "$configurationProductDir/$libraryName.framework/Versions/A/$libraryName";
646     }
647     if (isAppleWinWebKit()) {
648         if ($libraryName eq "JavaScriptCore") {
649             return "$baseProductDir/lib/$libraryName.lib";
650         } else {
651             return "$baseProductDir/$libraryName.intermediate/$configuration/$libraryName.intermediate/$libraryName.lib";
652         }
653     }
654
655     die "Unsupported platform, can't determine built library locations.\nTry `build-webkit --help` for more information.\n";
656 }
657
658 # Check to see that all the frameworks are built.
659 sub checkFrameworks # FIXME: This is a poor name since only the Mac calls built WebCore a Framework.
660 {
661     return if isCygwin() || isWindows();
662     my @frameworks = ("JavaScriptCore", "WebCore");
663     push(@frameworks, "WebKit") if isAppleMacWebKit(); # FIXME: This seems wrong, all ports should have a WebKit these days.
664     for my $framework (@frameworks) {
665         my $path = builtDylibPathForName($framework);
666         die "Can't find built framework at \"$path\".\n" unless -e $path;
667     }
668 }
669
670 sub isInspectorFrontend()
671 {
672     determineIsInspectorFrontend();
673     return $isInspectorFrontend;
674 }
675
676 sub determineIsInspectorFrontend()
677 {
678     return if defined($isInspectorFrontend);
679     $isInspectorFrontend = checkForArgumentAndRemoveFromARGV("--inspector-frontend");
680 }
681
682 sub isQt()
683 {
684     determineIsQt();
685     return $isQt;
686 }
687
688 sub isSymbian()
689 {
690     determineIsSymbian();
691     return $isSymbian;
692 }
693
694 sub qtFeatureDefaults()
695 {
696     determineQtFeatureDefaults();
697     return %qtFeatureDefaults;
698 }
699
700 sub commandExists($)
701 {
702     my $command = shift;
703     my $devnull = File::Spec->devnull();
704     return `$command --version 2> $devnull`;
705 }
706
707 sub determineQtFeatureDefaults()
708 {
709     return if %qtFeatureDefaults;
710     die "ERROR: qmake missing but required to build WebKit.\n" if not commandExists($qmakebin);
711     my $originalCwd = getcwd();
712     chdir File::Spec->catfile(sourceDir(), "Source", "WebCore");
713     my $defaults = `$qmakebin CONFIG+=compute_defaults 2>&1`;
714     chdir $originalCwd;
715
716     while ($defaults =~ m/(\S+?)=(\S+?)/gi) {
717         $qtFeatureDefaults{$1}=$2;
718     }
719 }
720
721 sub checkForArgumentAndRemoveFromARGV
722 {
723     my $argToCheck = shift;
724     return checkForArgumentAndRemoveFromArrayRef($argToCheck, \@ARGV);
725 }
726
727 sub checkForArgumentAndRemoveFromArrayRef
728 {
729     my ($argToCheck, $arrayRef) = @_;
730     my @indicesToRemove;
731     foreach my $index (0 .. $#$arrayRef) {
732         my $opt = $$arrayRef[$index];
733         if ($opt =~ /^$argToCheck$/i ) {
734             push(@indicesToRemove, $index);
735         }
736     }
737     foreach my $index (@indicesToRemove) {
738         splice(@$arrayRef, $index, 1);
739     }
740     return $#indicesToRemove > -1;
741 }
742
743 sub isWK2()
744 {
745     if (defined($isWK2)) {
746         return $isWK2;
747     }
748     if (checkForArgumentAndRemoveFromARGV("-2")) {
749         $isWK2 = 1;
750     } else {
751         $isWK2 = 0;
752     }
753     return $isWK2;
754 }
755
756 sub determineIsQt()
757 {
758     return if defined($isQt);
759
760     # Allow override in case QTDIR is not set.
761     if (checkForArgumentAndRemoveFromARGV("--qt")) {
762         $isQt = 1;
763         return;
764     }
765
766     # The presence of QTDIR only means Qt if --gtk or --wx or --efl are not on the command-line
767     if (isGtk() || isWx() || isEfl()) {
768         $isQt = 0;
769         return;
770     }
771     
772     $isQt = defined($ENV{'QTDIR'});
773 }
774
775 sub determineIsSymbian()
776 {
777     return if defined($isSymbian);
778
779     if (checkForArgumentAndRemoveFromARGV("--symbian")) {
780         $isSymbian = 1;
781         return;
782     }
783 }
784
785 sub determineIsEfl()
786 {
787     return if defined($isEfl);
788     $isEfl = checkForArgumentAndRemoveFromARGV("--efl");
789 }
790
791 sub isEfl()
792 {
793     determineIsEfl();
794     return $isEfl;
795 }
796
797 sub isGtk()
798 {
799     determineIsGtk();
800     return $isGtk;
801 }
802
803 sub determineIsGtk()
804 {
805     return if defined($isGtk);
806     $isGtk = checkForArgumentAndRemoveFromARGV("--gtk");
807 }
808
809 sub isWinCE()
810 {
811     determineIsWinCE();
812     return $isWinCE;
813 }
814
815 sub determineIsWinCE()
816 {
817     return if defined($isWinCE);
818     $isWinCE = checkForArgumentAndRemoveFromARGV("--wince");
819 }
820
821 sub isWx()
822 {
823     determineIsWx();
824     return $isWx;
825 }
826
827 sub determineIsWx()
828 {
829     return if defined($isWx);
830     $isWx = checkForArgumentAndRemoveFromARGV("--wx");
831 }
832
833 sub getWxArgs()
834 {
835     if (!@wxArgs) {
836         @wxArgs = ("");
837         my $rawWxArgs = "";
838         foreach my $opt (@ARGV) {
839             if ($opt =~ /^--wx-args/i ) {
840                 @ARGV = grep(!/^--wx-args/i, @ARGV);
841                 $rawWxArgs = $opt;
842                 $rawWxArgs =~ s/--wx-args=//i;
843             }
844         }
845         @wxArgs = split(/,/, $rawWxArgs);
846     }
847     return @wxArgs;
848 }
849
850 # Determine if this is debian, ubuntu, linspire, or something similar.
851 sub isDebianBased()
852 {
853     return -e "/etc/debian_version";
854 }
855
856 sub isFedoraBased()
857 {
858     return -e "/etc/fedora-release";
859 }
860
861 sub isChromium()
862 {
863     determineIsChromium();
864     return $isChromium;
865 }
866
867 sub determineIsChromium()
868 {
869     return if defined($isChromium);
870     $isChromium = checkForArgumentAndRemoveFromARGV("--chromium");
871 }
872
873 sub isWinCairo()
874 {
875     determineIsWinCairo();
876     return $isWinCairo;
877 }
878
879 sub determineIsWinCairo()
880 {
881     return if defined($isWinCairo);
882     $isWinCairo = checkForArgumentAndRemoveFromARGV("--wincairo");
883 }
884
885 sub isCygwin()
886 {
887     return ($^O eq "cygwin") || 0;
888 }
889
890 sub isAnyWindows()
891 {
892     return isWindows() || isCygwin() || isMsys();
893 }
894
895 sub determineWinVersion()
896 {
897     return if $winVersion;
898
899     if (!isAnyWindows()) {
900         $winVersion = -1;
901         return;
902     }
903
904     my $versionString = `cmd /c ver`;
905     $versionString =~ /(\d)\.(\d)\.(\d+)/;
906
907     $winVersion = {
908         major => $1,
909         minor => $2,
910         build => $3,
911     };
912 }
913
914 sub winVersion()
915 {
916     determineWinVersion();
917     return $winVersion;
918 }
919
920 sub isWindows7SP0()
921 {
922     return isAnyWindows() && winVersion()->{major} == 6 && winVersion()->{minor} == 1 && winVersion()->{build} == 7600;
923 }
924
925 sub isWindowsVista()
926 {
927     return isAnyWindows() && winVersion()->{major} == 6 && winVersion()->{minor} == 0;
928 }
929
930 sub isWindowsXP()
931 {
932     return isAnyWindows() && winVersion()->{major} == 5 && winVersion()->{minor} == 1;
933 }
934
935 sub isDarwin()
936 {
937     return ($^O eq "darwin") || 0;
938 }
939
940 sub isWindows()
941 {
942     return ($^O eq "MSWin32") || 0;
943 }
944
945 sub isMsys()
946 {
947     return ($^O eq "msys") || 0;
948 }
949
950 sub isLinux()
951 {
952     return ($^O eq "linux") || 0;
953 }
954
955 sub isAppleWebKit()
956 {
957     return !(isQt() or isGtk() or isWx() or isChromium() or isEfl() or isWinCE());
958 }
959
960 sub isAppleMacWebKit()
961 {
962     return isAppleWebKit() && isDarwin();
963 }
964
965 sub isAppleWinWebKit()
966 {
967     return isAppleWebKit() && (isCygwin() || isWindows());
968 }
969
970 sub isPerianInstalled()
971 {
972     if (!isAppleWebKit()) {
973         return 0;
974     }
975
976     if (-d "/Library/QuickTime/Perian.component") {
977         return 1;
978     }
979
980     if (-d "$ENV{HOME}/Library/QuickTime/Perian.component") {
981         return 1;
982     }
983
984     return 0;
985 }
986
987 sub determineOSXVersion()
988 {
989     return if $osXVersion;
990
991     if (!isDarwin()) {
992         $osXVersion = -1;
993         return;
994     }
995
996     my $version = `sw_vers -productVersion`;
997     my @splitVersion = split(/\./, $version);
998     @splitVersion >= 2 or die "Invalid version $version";
999     $osXVersion = {
1000             "major" => $splitVersion[0],
1001             "minor" => $splitVersion[1],
1002             "subminor" => (defined($splitVersion[2]) ? $splitVersion[2] : 0),
1003     };
1004 }
1005
1006 sub osXVersion()
1007 {
1008     determineOSXVersion();
1009     return $osXVersion;
1010 }
1011
1012 sub isTiger()
1013 {
1014     return isDarwin() && osXVersion()->{"minor"} == 4;
1015 }
1016
1017 sub isLeopard()
1018 {
1019     return isDarwin() && osXVersion()->{"minor"} == 5;
1020 }
1021
1022 sub isSnowLeopard()
1023 {
1024     return isDarwin() && osXVersion()->{"minor"} == 6;
1025 }
1026
1027 sub isWindowsNT()
1028 {
1029     return $ENV{'OS'} eq 'Windows_NT';
1030 }
1031
1032 sub relativeScriptsDir()
1033 {
1034     my $scriptDir = File::Spec->catpath("", File::Spec->abs2rel($FindBin::Bin, getcwd()), "");
1035     if ($scriptDir eq "") {
1036         $scriptDir = ".";
1037     }
1038     return $scriptDir;
1039 }
1040
1041 sub launcherPath()
1042 {
1043     my $relativeScriptsPath = relativeScriptsDir();
1044     if (isGtk() || isQt() || isWx() || isEfl() || isWinCE()) {
1045         return "$relativeScriptsPath/run-launcher";
1046     } elsif (isAppleWebKit()) {
1047         return "$relativeScriptsPath/run-safari";
1048     }
1049 }
1050
1051 sub launcherName()
1052 {
1053     if (isGtk()) {
1054         return "GtkLauncher";
1055     } elsif (isQt()) {
1056         return "QtTestBrowser";
1057     } elsif (isWx()) {
1058         return "wxBrowser";
1059     } elsif (isAppleWebKit()) {
1060         return "Safari";
1061     } elsif (isEfl()) {
1062         return "EWebLauncher";
1063     } elsif (isWinCE()) {
1064         return "WinCELauncher";
1065     }
1066 }
1067
1068 sub checkRequiredSystemConfig
1069 {
1070     if (isDarwin()) {
1071         chomp(my $productVersion = `sw_vers -productVersion`);
1072         if (eval "v$productVersion" lt v10.4) {
1073             print "*************************************************************\n";
1074             print "Mac OS X Version 10.4.0 or later is required to build WebKit.\n";
1075             print "You have " . $productVersion . ", thus the build will most likely fail.\n";
1076             print "*************************************************************\n";
1077         }
1078         my $xcodebuildVersionOutput = `xcodebuild -version`;
1079         my $devToolsCoreVersion = ($xcodebuildVersionOutput =~ /DevToolsCore-(\d+)/) ? $1 : undef;
1080         my $xcodeVersion = ($xcodebuildVersionOutput =~ /Xcode ([0-9](\.[0-9]+)*)/) ? $1 : undef;
1081         if (!$devToolsCoreVersion && !$xcodeVersion
1082             || $devToolsCoreVersion && $devToolsCoreVersion < 747
1083             || $xcodeVersion && eval "v$xcodeVersion" lt v2.3) {
1084             print "*************************************************************\n";
1085             print "Xcode Version 2.3 or later is required to build WebKit.\n";
1086             print "You have an earlier version of Xcode, thus the build will\n";
1087             print "most likely fail.  The latest Xcode is available from the web:\n";
1088             print "http://developer.apple.com/tools/xcode\n";
1089             print "*************************************************************\n";
1090         }
1091     } elsif (isGtk() or isQt() or isWx() or isEfl()) {
1092         my @cmds = qw(flex bison gperf);
1093         my @missing = ();
1094         foreach my $cmd (@cmds) {
1095             push @missing, $cmd if not commandExists($cmd);
1096         }
1097
1098         if (@missing) {
1099             my $list = join ", ", @missing;
1100             die "ERROR: $list missing but required to build WebKit.\n";
1101         }
1102     }
1103     # Win32 and other platforms may want to check for minimum config
1104 }
1105
1106 sub determineWindowsSourceDir()
1107 {
1108     return if $windowsSourceDir;
1109     $windowsSourceDir = sourceDir();
1110     chomp($windowsSourceDir = `cygpath -w '$windowsSourceDir'`) if isCygwin();
1111 }
1112
1113 sub windowsSourceDir()
1114 {
1115     determineWindowsSourceDir();
1116     return $windowsSourceDir;
1117 }
1118
1119 sub windowsLibrariesDir()
1120 {
1121     return windowsSourceDir() . "\\WebKitLibraries\\win";
1122 }
1123
1124 sub windowsOutputDir()
1125 {
1126     return windowsSourceDir() . "\\WebKitBuild";
1127 }
1128
1129 sub setupAppleWinEnv()
1130 {
1131     return unless isAppleWinWebKit();
1132
1133     if (isWindowsNT()) {
1134         my $restartNeeded = 0;
1135         my %variablesToSet = ();
1136
1137         # Setting the environment variable 'CYGWIN' to 'tty' makes cygwin enable extra support (i.e., termios)
1138         # for UNIX-like ttys in the Windows console
1139         $variablesToSet{CYGWIN} = "tty" unless $ENV{CYGWIN};
1140         
1141         # Those environment variables must be set to be able to build inside Visual Studio.
1142         $variablesToSet{WEBKITLIBRARIESDIR} = windowsLibrariesDir() unless $ENV{WEBKITLIBRARIESDIR};
1143         $variablesToSet{WEBKITOUTPUTDIR} = windowsOutputDir() unless $ENV{WEBKITOUTPUTDIR};
1144
1145         foreach my $variable (keys %variablesToSet) {
1146             print "Setting the Environment Variable '" . $variable . "' to '" . $variablesToSet{$variable} . "'\n\n";
1147             system qw(regtool -s set), '\\HKEY_CURRENT_USER\\Environment\\' . $variable, $variablesToSet{$variable};
1148             $restartNeeded ||= $variable eq "WEBKITLIBRARIESDIR" || $variable eq "WEBKITOUTPUTDIR";
1149         }
1150
1151         if ($restartNeeded) {
1152             print "Please restart your computer before attempting to build inside Visual Studio.\n\n";
1153         }
1154     } else {
1155         if (!$ENV{'WEBKITLIBRARIESDIR'}) {
1156             print "Warning: You must set the 'WebKitLibrariesDir' environment variable\n";
1157             print "         to be able build WebKit from within Visual Studio.\n";
1158             print "         Make sure that 'WebKitLibrariesDir' points to the\n";
1159             print "         'WebKitLibraries/win' directory, not the 'WebKitLibraries/' directory.\n\n";
1160         }
1161         if (!$ENV{'WEBKITOUTPUTDIR'}) {
1162             print "Warning: You must set the 'WebKitOutputDir' environment variable\n";
1163             print "         to be able build WebKit from within Visual Studio.\n\n";
1164         }
1165     }
1166 }
1167
1168 sub setupCygwinEnv()
1169 {
1170     return if !isCygwin() && !isWindows();
1171     return if $vcBuildPath;
1172
1173     my $vsInstallDir;
1174     my $programFilesPath = $ENV{'PROGRAMFILES(X86)'} || $ENV{'PROGRAMFILES'} || "C:\\Program Files";
1175     if ($ENV{'VSINSTALLDIR'}) {
1176         $vsInstallDir = $ENV{'VSINSTALLDIR'};
1177     } else {
1178         $vsInstallDir = File::Spec->catdir($programFilesPath, "Microsoft Visual Studio 8");
1179     }
1180     chomp($vsInstallDir = `cygpath "$vsInstallDir"`) if isCygwin();
1181     $vcBuildPath = File::Spec->catfile($vsInstallDir, qw(Common7 IDE devenv.com));
1182     if (-e $vcBuildPath) {
1183         # Visual Studio is installed; we can use pdevenv to build.
1184         # FIXME: Make pdevenv work with non-Cygwin Perl.
1185         $vcBuildPath = File::Spec->catfile(sourceDir(), qw(Tools Scripts pdevenv)) if isCygwin();
1186     } else {
1187         # Visual Studio not found, try VC++ Express
1188         $vcBuildPath = File::Spec->catfile($vsInstallDir, qw(Common7 IDE VCExpress.exe));
1189         if (! -e $vcBuildPath) {
1190             print "*************************************************************\n";
1191             print "Cannot find '$vcBuildPath'\n";
1192             print "Please execute the file 'vcvars32.bat' from\n";
1193             print "'$programFilesPath\\Microsoft Visual Studio 8\\VC\\bin\\'\n";
1194             print "to setup the necessary environment variables.\n";
1195             print "*************************************************************\n";
1196             die;
1197         }
1198         $willUseVCExpressWhenBuilding = 1;
1199     }
1200
1201     my $qtSDKPath = File::Spec->catdir($programFilesPath, "QuickTime SDK");
1202     if (0 && ! -e $qtSDKPath) {
1203         print "*************************************************************\n";
1204         print "Cannot find '$qtSDKPath'\n";
1205         print "Please download the QuickTime SDK for Windows from\n";
1206         print "http://developer.apple.com/quicktime/download/\n";
1207         print "*************************************************************\n";
1208         die;
1209     }
1210     
1211     unless ($ENV{WEBKITLIBRARIESDIR}) {
1212         $ENV{'WEBKITLIBRARIESDIR'} = File::Spec->catdir($sourceDir, "WebKitLibraries", "win");
1213         chomp($ENV{WEBKITLIBRARIESDIR} = `cygpath -wa $ENV{WEBKITLIBRARIESDIR}`) if isCygwin();
1214     }
1215
1216     print "Building results into: ", baseProductDir(), "\n";
1217     print "WEBKITOUTPUTDIR is set to: ", $ENV{"WEBKITOUTPUTDIR"}, "\n";
1218     print "WEBKITLIBRARIESDIR is set to: ", $ENV{"WEBKITLIBRARIESDIR"}, "\n";
1219 }
1220
1221 sub dieIfWindowsPlatformSDKNotInstalled
1222 {
1223     my $registry32Path = "/proc/registry/";
1224     my $registry64Path = "/proc/registry64/";
1225     my $windowsPlatformSDKRegistryEntry = "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MicrosoftSDK/InstalledSDKs/D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1";
1226
1227     # FIXME: It would be better to detect whether we are using 32- or 64-bit Windows
1228     # and only check the appropriate entry. But for now we just blindly check both.
1229     return if (-e $registry32Path . $windowsPlatformSDKRegistryEntry) || (-e $registry64Path . $windowsPlatformSDKRegistryEntry);
1230
1231     print "*************************************************************\n";
1232     print "Cannot find registry entry '$windowsPlatformSDKRegistryEntry'.\n";
1233     print "Please download and install the Microsoft Windows Server 2003 R2\n";
1234     print "Platform SDK from <http://www.microsoft.com/downloads/details.aspx?\n";
1235     print "familyid=0baf2b35-c656-4969-ace8-e4c0c0716adb&displaylang=en>.\n\n";
1236     print "Then follow step 2 in the Windows section of the \"Installing Developer\n";
1237     print "Tools\" instructions at <http://www.webkit.org/building/tools.html>.\n";
1238     print "*************************************************************\n";
1239     die;
1240 }
1241
1242 sub copyInspectorFrontendFiles
1243 {
1244     my $productDir = productDir();
1245     my $sourceInspectorPath = sourceDir() . "/Source/WebCore/inspector/front-end/";
1246     my $inspectorResourcesDirPath = $ENV{"WEBKITINSPECTORRESOURCESDIR"};
1247
1248     if (!defined($inspectorResourcesDirPath)) {
1249         $inspectorResourcesDirPath = "";
1250     }
1251
1252     if (isAppleMacWebKit()) {
1253         $inspectorResourcesDirPath = $productDir . "/WebCore.framework/Resources/inspector";
1254     } elsif (isAppleWinWebKit()) {
1255         $inspectorResourcesDirPath = $productDir . "/WebKit.resources/inspector";
1256     } elsif (isQt() || isGtk()) {
1257         my $prefix = $ENV{"WebKitInstallationPrefix"};
1258         $inspectorResourcesDirPath = (defined($prefix) ? $prefix : "/usr/share") . "/webkit-1.0/webinspector";
1259     } elsif (isEfl()) {
1260         my $prefix = $ENV{"WebKitInstallationPrefix"};
1261         $inspectorResourcesDirPath = (defined($prefix) ? $prefix : "/usr/share") . "/ewebkit/webinspector";
1262     }
1263
1264     if (! -d $inspectorResourcesDirPath) {
1265         print "*************************************************************\n";
1266         print "Cannot find '$inspectorResourcesDirPath'.\n" if (defined($inspectorResourcesDirPath));
1267         print "Make sure that you have built WebKit first.\n" if (! -d $productDir || defined($inspectorResourcesDirPath));
1268         print "Optionally, set the environment variable 'WebKitInspectorResourcesDir'\n";
1269         print "to point to the directory that contains the WebKit Inspector front-end\n";
1270         print "files for the built WebCore framework.\n";
1271         print "*************************************************************\n";
1272         die;
1273     }
1274     return system "rsync", "-aut", "--exclude=/.DS_Store", "--exclude=*.re2js", "--exclude=.svn/", !isQt() ? "--exclude=/WebKit.qrc" : "", $sourceInspectorPath, $inspectorResourcesDirPath;
1275 }
1276
1277 sub buildXCodeProject($$@)
1278 {
1279     my ($project, $clean, @extraOptions) = @_;
1280
1281     if ($clean) {
1282         push(@extraOptions, "-alltargets");
1283         push(@extraOptions, "clean");
1284     }
1285
1286     return system "xcodebuild", "-project", "$project.xcodeproj", @extraOptions;
1287 }
1288
1289 sub usingVisualStudioExpress()
1290 {
1291     setupCygwinEnv();
1292     return $willUseVCExpressWhenBuilding;
1293 }
1294
1295 sub buildVisualStudioProject
1296 {
1297     my ($project, $clean) = @_;
1298     setupCygwinEnv();
1299
1300     my $config = configurationForVisualStudio();
1301
1302     dieIfWindowsPlatformSDKNotInstalled() if $willUseVCExpressWhenBuilding;
1303
1304     chomp($project = `cygpath -w "$project"`) if isCygwin();
1305     
1306     my $action = "/build";
1307     if ($clean) {
1308         $action = "/clean";
1309     }
1310
1311     my @command = ($vcBuildPath, $project, $action, $config);
1312
1313     print join(" ", @command), "\n";
1314     return system @command;
1315 }
1316
1317 sub downloadWafIfNeeded
1318 {
1319     # get / update waf if needed
1320     my $waf = "$sourceDir/Tools/waf/waf";
1321     my $wafURL = 'http://wxwebkit.kosoftworks.com/downloads/deps/waf';
1322     if (!-f $waf) {
1323         my $result = system "curl -o $waf $wafURL";
1324         chmod 0755, $waf;
1325     }
1326 }
1327
1328 sub buildWafProject
1329 {
1330     my ($project, $shouldClean, @options) = @_;
1331     
1332     # set the PYTHONPATH for waf
1333     my $pythonPath = $ENV{'PYTHONPATH'};
1334     if (!defined($pythonPath)) {
1335         $pythonPath = '';
1336     }
1337     my $sourceDir = sourceDir();
1338     my $newPythonPath = "$sourceDir/Tools/waf/build:$pythonPath";
1339     if (isCygwin()) {
1340         $newPythonPath = `cygpath --mixed --path $newPythonPath`;
1341     }
1342     $ENV{'PYTHONPATH'} = $newPythonPath;
1343     
1344     print "Building $project\n";
1345
1346     my $wafCommand = "$sourceDir/Tools/waf/waf";
1347     if ($ENV{'WXWEBKIT_WAF'}) {
1348         $wafCommand = $ENV{'WXWEBKIT_WAF'};
1349     }
1350     if (isCygwin()) {
1351         $wafCommand = `cygpath --windows "$wafCommand"`;
1352         chomp($wafCommand);
1353     }
1354     if ($shouldClean) {
1355         return system $wafCommand, "uninstall", "clean", "distclean";
1356     }
1357     
1358     return system $wafCommand, 'configure', 'build', 'install', @options;
1359 }
1360
1361 sub retrieveQMakespecVar
1362 {
1363     my $mkspec = $_[0];
1364     my $varname = $_[1];
1365
1366     my $varvalue = undef;
1367     #print "retrieveMakespecVar " . $mkspec . ", " . $varname . "\n";
1368
1369     local *SPEC;
1370     open SPEC, "<$mkspec" or return $varvalue;
1371     while (<SPEC>) {
1372         if ($_ =~ /\s*include\((.+)\)/) {
1373             # open the included mkspec
1374             my $oldcwd = getcwd();
1375             (my $volume, my $directories, my $file) = File::Spec->splitpath($mkspec);
1376             my $newcwd = "$volume$directories";
1377             chdir $newcwd if $newcwd;
1378             $varvalue = retrieveQMakespecVar($1, $varname);
1379             chdir $oldcwd;
1380         } elsif ($_ =~ /$varname\s*=\s*([^\s]+)/) {
1381             $varvalue = $1;
1382             last;
1383         }
1384     }
1385     close SPEC;
1386     return $varvalue;
1387 }
1388
1389 sub qtMakeCommand($)
1390 {
1391     my ($qmakebin) = @_;
1392     chomp(my $mkspec = `$qmakebin -query QMAKE_MKSPECS`);
1393     $mkspec .= "/default";
1394     my $compiler = retrieveQMakespecVar("$mkspec/qmake.conf", "QMAKE_CC");
1395
1396     #print "default spec: " . $mkspec . "\n";
1397     #print "compiler found: " . $compiler . "\n";
1398
1399     if ($compiler && $compiler eq "cl") {
1400         return "nmake";
1401     }
1402
1403     return "make";
1404 }
1405
1406 sub autotoolsFlag($$)
1407 {
1408     my ($flag, $feature) = @_;
1409     my $prefix = $flag ? "--enable" : "--disable";
1410
1411     return $prefix . '-' . $feature;
1412 }
1413
1414 sub autogenArgumentsHaveChanged($@)
1415 {
1416     my ($filename, @currentArguments) = @_;
1417
1418     if (! -e $filename) {
1419         return 1;
1420     }
1421
1422     open(AUTOTOOLS_ARGUMENTS, $filename);
1423     chomp(my $previousArguments = <AUTOTOOLS_ARGUMENTS>);
1424     close(AUTOTOOLS_ARGUMENTS);
1425
1426     return $previousArguments ne join(" ", @currentArguments);
1427 }
1428
1429 sub buildAutotoolsProject($@)
1430 {
1431     my ($project, $clean, @buildParams) = @_;
1432
1433     my $make = 'make';
1434     my $dir = productDir();
1435     my $config = passedConfiguration() || configuration();
1436     my $prefix;
1437
1438     my @buildArgs = ();
1439     my $makeArgs = $ENV{"WebKitMakeArguments"} || "";
1440     for my $i (0 .. $#buildParams) {
1441         my $opt = $buildParams[$i];
1442         if ($opt =~ /^--makeargs=(.*)/i ) {
1443             $makeArgs = $makeArgs . " " . $1;
1444         } elsif ($opt =~ /^--prefix=(.*)/i ) {
1445             $prefix = $1;
1446         } else {
1447             push @buildArgs, $opt;
1448         }
1449     }
1450
1451     # Automatically determine the number of CPUs for make only
1452     # if make arguments haven't already been specified.
1453     if ($makeArgs eq "") {
1454         $makeArgs = "-j" . numberOfCPUs();
1455     }
1456
1457     # WebKit is the default target, so we don't need to specify anything.
1458     if ($project eq "JavaScriptCore") {
1459         $makeArgs .= " jsc";
1460     }
1461
1462     $prefix = $ENV{"WebKitInstallationPrefix"} if !defined($prefix);
1463     push @buildArgs, "--prefix=" . $prefix if defined($prefix);
1464
1465     # check if configuration is Debug
1466     if ($config =~ m/debug/i) {
1467         push @buildArgs, "--enable-debug";
1468     } else {
1469         push @buildArgs, "--disable-debug";
1470     }
1471
1472     # Use rm to clean the build directory since distclean may miss files
1473     if ($clean && -d $dir) {
1474         system "rm", "-rf", "$dir";
1475     }
1476
1477     if (! -d $dir) {
1478         File::Path::mkpath($dir) or die "Failed to create build directory " . $dir
1479     }
1480     chdir $dir or die "Failed to cd into " . $dir . "\n";
1481
1482     if ($clean) {
1483         return 0;
1484     }
1485
1486     # If GNUmakefile exists, don't run autogen.sh. The makefile should be
1487     # smart enough to track autotools dependencies and re-run autogen.sh
1488     # when build files change.
1489     my $autogenArgumentsFile = "previous-autogen-arguments.txt";
1490     my $result;
1491     if (!(-e "GNUmakefile") or autogenArgumentsHaveChanged($autogenArgumentsFile, @buildArgs)) {
1492
1493         # Write autogen.sh arguments to a file so that we can detect
1494         # when they change and automatically re-run it.
1495         open(AUTOTOOLS_ARGUMENTS, ">$autogenArgumentsFile");
1496         print AUTOTOOLS_ARGUMENTS  join(" ", @buildArgs);
1497         close(AUTOTOOLS_ARGUMENTS);
1498
1499         print "Calling configure in " . $dir . "\n\n";
1500         print "Installation prefix directory: $prefix\n" if(defined($prefix));
1501
1502         # Make the path relative since it will appear in all -I compiler flags.
1503         # Long argument lists cause bizarre slowdowns in libtool.
1504         my $relSourceDir = File::Spec->abs2rel($sourceDir) || ".";
1505         $result = system "$relSourceDir/autogen.sh", @buildArgs;
1506         if ($result ne 0) {
1507             die "Failed to setup build environment using 'autotools'!\n";
1508         }
1509     }
1510
1511     $result = system "$make $makeArgs";
1512     if ($result ne 0) {
1513         die "\nFailed to build WebKit using '$make'!\n";
1514     }
1515
1516     chdir ".." or die;
1517     return $result;
1518 }
1519
1520 sub generateBuildSystemFromCMakeProject
1521 {
1522     my ($port, $prefixPath, @cmakeArgs) = @_;
1523     my $config = configuration();
1524     my $buildPath = File::Spec->catdir(baseProductDir(), $config);
1525     File::Path::mkpath($buildPath) unless -d $buildPath;
1526     my $originalWorkingDirectory = getcwd();
1527     chdir($buildPath) or die;
1528
1529     my @args;
1530     push @args, "-DPORT=\"$port\"";
1531     push @args, "-DCMAKE_INSTALL_PREFIX=\"$prefixPath\"" if $prefixPath;
1532     if ($config =~ /release/i) {
1533         push @args, "-DCMAKE_BUILD_TYPE=Release";
1534     } elsif ($config =~ /debug/i) {
1535         push @args, "-DCMAKE_BUILD_TYPE=Debug";
1536     }
1537     push @args, @cmakeArgs if @cmakeArgs;
1538     push @args, '"' . File::Spec->catdir(sourceDir(), "Source") . '"';
1539
1540     # We call system("cmake @args") instead of system("cmake", @args) so that @args is
1541     # parsed for shell metacharacters.
1542     my $returnCode = system("cmake @args");
1543
1544     chdir($originalWorkingDirectory);
1545     return $returnCode;
1546 }
1547
1548 sub buildCMakeGeneratedProject($)
1549 {
1550     my ($makeArgs) = @_;
1551     my $config = configuration();
1552     my $buildPath = File::Spec->catdir(baseProductDir(), $config);
1553     if (! -d $buildPath) {
1554         die "Must call generateBuildSystemFromCMakeProject() before building CMake project.";
1555     }
1556     my @args = ("--build", $buildPath, "--config", $config);
1557     push @args, ("--", $makeArgs) if $makeArgs;
1558
1559     # We call system("cmake @args") instead of system("cmake", @args) so that @args is
1560     # parsed for shell metacharacters. In particular, $makeArgs may contain such metacharacters.
1561     return system("cmake @args");
1562 }
1563
1564 sub cleanCMakeGeneratedProject()
1565 {
1566     my $config = configuration();
1567     my $buildPath = File::Spec->catdir(baseProductDir(), $config);
1568     if (-d $buildPath) {
1569         return system("cmake", "--build", $buildPath, "--config", $config, "--target", "clean");
1570     }
1571     return 0;
1572 }
1573
1574 sub buildCMakeProjectOrExit($$$$@)
1575 {
1576     my ($clean, $port, $prefixPath, $makeArgs, @cmakeArgs) = @_;
1577     my $returnCode;
1578     if ($clean) {
1579         $returnCode = exitStatus(cleanCMakeGeneratedProject());
1580         exit($returnCode) if $returnCode;
1581     }
1582     $returnCode = exitStatus(generateBuildSystemFromCMakeProject($port, $prefixPath, @cmakeArgs));
1583     exit($returnCode) if $returnCode;
1584     $returnCode = exitStatus(buildCMakeGeneratedProject($makeArgs));
1585     exit($returnCode) if $returnCode;
1586 }
1587
1588 sub buildQMakeProject($@)
1589 {
1590     my ($project, $clean, @buildParams) = @_;
1591
1592     my @subdirs = ("JavaScriptCore", "WebCore", "WebKit/qt/Api");
1593     if (grep { $_ eq $project } @subdirs) {
1594         @subdirs = ($project);
1595     } else {
1596         $project = 0;
1597     }
1598
1599     my @buildArgs = ("-r");
1600
1601     my $makeargs = "";
1602     my $installHeaders;
1603     my $installLibs;
1604     for my $i (0 .. $#buildParams) {
1605         my $opt = $buildParams[$i];
1606         if ($opt =~ /^--qmake=(.*)/i ) {
1607             $qmakebin = $1;
1608         } elsif ($opt =~ /^--qmakearg=(.*)/i ) {
1609             push @buildArgs, $1;
1610         } elsif ($opt =~ /^--makeargs=(.*)/i ) {
1611             $makeargs = $1;
1612         } elsif ($opt =~ /^--install-headers=(.*)/i ) {
1613             $installHeaders = $1;
1614         } elsif ($opt =~ /^--install-libs=(.*)/i ) {
1615             $installLibs = $1;
1616         } else {
1617             push @buildArgs, $opt;
1618         }
1619     }
1620
1621     my $make = qtMakeCommand($qmakebin);
1622     my $config = configuration();
1623     push @buildArgs, "INSTALL_HEADERS=" . $installHeaders if defined($installHeaders);
1624     push @buildArgs, "INSTALL_LIBS=" . $installLibs if defined($installLibs);
1625     my $dir = File::Spec->canonpath(productDir());
1626
1627
1628     # On Symbian qmake needs to run in the same directory where the pro file is located.
1629     if (isSymbian()) {
1630         $dir = $sourceDir . "/Source";
1631     }
1632
1633     File::Path::mkpath($dir);
1634     chdir $dir or die "Failed to cd into " . $dir . "\n";
1635
1636     print "Generating derived sources\n\n";
1637
1638     push @buildArgs, "OUTPUT_DIR=" . $dir;
1639
1640     my @dsQmakeArgs = @buildArgs;
1641     push @dsQmakeArgs, "-r";
1642     push @dsQmakeArgs, sourceDir() . "/Source/DerivedSources.pro";
1643     if ($project) {
1644         push @dsQmakeArgs, "-after SUBDIRS=" . $project. "/DerivedSources.pro";
1645     }
1646     push @dsQmakeArgs, "-o Makefile.DerivedSources";
1647     print "Calling '$qmakebin @dsQmakeArgs' in " . $dir . "\n\n";
1648     my $result = system "$qmakebin @dsQmakeArgs";
1649     if ($result ne 0) {
1650         die "Failed while running $qmakebin to generate derived sources!\n";
1651     }
1652
1653     if ($project ne "JavaScriptCore") {
1654         # FIXME: Iterate over different source directories manually to workaround a problem with qmake+extraTargets+s60
1655         # To avoid overwriting of Makefile.DerivedSources in the root dir use Makefile.DerivedSources.Tools for Tools
1656         if (grep { $_ eq "CONFIG+=webkit2"} @buildArgs) {
1657             push @subdirs, "WebKit2";
1658             if ( -e sourceDir() ."/Tools/DerivedSources.pro" ) {
1659                 @dsQmakeArgs = @buildArgs;
1660                 push @dsQmakeArgs, "-r";
1661                 push @dsQmakeArgs, sourceDir() . "/Tools/DerivedSources.pro";
1662                 push @dsQmakeArgs, "-o Makefile.DerivedSources.Tools";
1663                 print "Calling '$qmakebin @dsQmakeArgs' in " . $dir . "\n\n";
1664                 my $result = system "$qmakebin @dsQmakeArgs";
1665                 if ($result ne 0) {
1666                     die "Failed while running $qmakebin to generate derived sources for Tools!\n";
1667                 }
1668                 push @subdirs, "WebKitTestRunner";
1669             }
1670         }
1671     }
1672
1673     for my $subdir (@subdirs) {
1674         my $dsMakefile = "Makefile.DerivedSources";
1675         print "Calling '$make $makeargs -C $subdir -f $dsMakefile generated_files' in " . $dir . "/$subdir\n\n";
1676         if ($make eq "nmake") {
1677             my $subdirWindows = $subdir;
1678             $subdirWindows =~ s:/:\\:g;
1679             $result = system "pushd $subdirWindows && $make $makeargs -f $dsMakefile generated_files && popd";
1680         } else {
1681             $result = system "$make $makeargs -C $subdir -f $dsMakefile generated_files";
1682         }
1683         if ($result ne 0) {
1684             die "Failed to generate ${subdir}'s derived sources!\n";
1685         }
1686     }
1687
1688     if ($config =~ m/debug/i) {
1689         push @buildArgs, "CONFIG-=release";
1690         push @buildArgs, "CONFIG+=debug";
1691     } else {
1692         my $passedConfig = passedConfiguration() || "";
1693         if (!isDarwin() || $passedConfig =~ m/release/i) {
1694             push @buildArgs, "CONFIG+=release";
1695             push @buildArgs, "CONFIG-=debug";
1696         } else {
1697             push @buildArgs, "CONFIG+=debug";
1698             push @buildArgs, "CONFIG+=debug_and_release";
1699         }
1700     }
1701
1702     if ($project) {
1703         push @buildArgs, "-after SUBDIRS=" . $project . "/" . $project . ".pro ";
1704         if ($project eq "JavaScriptCore") {
1705             push @buildArgs, "-after SUBDIRS+=" . $project . "/jsc.pro ";
1706         }
1707     }
1708     push @buildArgs, sourceDir() . "/Source/WebKit.pro";
1709     print "Calling '$qmakebin @buildArgs' in " . $dir . "\n\n";
1710     print "Installation headers directory: $installHeaders\n" if(defined($installHeaders));
1711     print "Installation libraries directory: $installLibs\n" if(defined($installLibs));
1712
1713     $result = system "$qmakebin @buildArgs";
1714     if ($result ne 0) {
1715        die "Failed to setup build environment using $qmakebin!\n";
1716     }
1717
1718     my $makefile = "";
1719     if (!$project) {
1720         $buildArgs[-1] = sourceDir() . "/Tools/Tools.pro";
1721         $makefile = "Makefile.Tools";
1722
1723         # On Symbian qmake needs to run in the same directory where the pro file is located.
1724         if (isSymbian()) {
1725             $dir = $sourceDir . "/Tools";
1726             chdir $dir or die "Failed to cd into " . $dir . "\n";
1727             $makefile = "bld.inf";
1728         }
1729
1730         print "Calling '$qmakebin @buildArgs -o $makefile' in " . $dir . "\n\n";
1731         $result = system "$qmakebin @buildArgs -o $makefile";
1732         if ($result ne 0) {
1733             die "Failed to setup build environment using $qmakebin!\n";
1734         }
1735     }
1736
1737     if (!$project) {
1738         # Manually create makefiles for the examples so we don't build by default
1739         my $examplesDir = $dir . "/WebKit/qt/examples";
1740         File::Path::mkpath($examplesDir);
1741         $buildArgs[-1] = sourceDir() . "/Source/WebKit/qt/examples/examples.pro";
1742         chdir $examplesDir or die;
1743         print "Calling '$qmakebin @buildArgs' in " . $examplesDir . "\n\n";
1744         $result = system "$qmakebin @buildArgs";
1745         die "Failed to create makefiles for the examples!\n" if $result ne 0;
1746         chdir $dir or die;
1747     }
1748
1749     my $makeTools = "echo";
1750     if (!$project) {
1751         $makeTools = "echo No Makefile for Tools. Skipping make";
1752
1753         if (-e "$dir/$makefile") {
1754             $makeTools = "$make $makeargs -f $makefile";
1755         }
1756     }
1757
1758     if ($clean) {
1759       print "Calling '$make $makeargs distclean' in " . $dir . "\n\n";
1760       $result = system "$make $makeargs distclean";
1761       $result = $result || system "$makeTools distclean";
1762     } elsif (isSymbian()) {
1763       print "\n\nWebKit is now configured for building, but you have to make\n";
1764       print "a choice about the target yourself. To start the build run:\n\n";
1765       print "    make release-armv5|debug-winscw|etc.\n\n";
1766     } else {
1767       print "Calling '$make $makeargs' in " . $dir . "\n\n";
1768       $result = system "$make $makeargs";
1769       $result = $result || system "$makeTools";
1770     }
1771
1772     chdir ".." or die;
1773     return $result;
1774 }
1775
1776 sub buildQMakeQtProject($$@)
1777 {
1778     my ($project, $clean, @buildArgs) = @_;
1779
1780     return buildQMakeProject("", $clean, @buildArgs);
1781 }
1782
1783 sub buildGtkProject
1784 {
1785     my ($project, $clean, @buildArgs) = @_;
1786
1787     if ($project ne "WebKit" and $project ne "JavaScriptCore") {
1788         die "Unsupported project: $project. Supported projects: WebKit, JavaScriptCore\n";
1789     }
1790
1791     return buildAutotoolsProject($project, $clean, @buildArgs);
1792 }
1793
1794 sub buildChromiumMakefile($$)
1795 {
1796     my ($target, $clean) = @_;
1797     if ($clean) {
1798         return system qw(rm -rf out);
1799     }
1800     my $config = configuration();
1801     my $numCpus = numberOfCPUs();
1802     my @command = ("make", "-fMakefile.chromium", "-j$numCpus", "BUILDTYPE=$config", $target);
1803     print join(" ", @command) . "\n";
1804     return system @command;
1805 }
1806
1807 sub buildChromiumVisualStudioProject($$)
1808 {
1809     my ($projectPath, $clean) = @_;
1810
1811     my $config = configuration();
1812     my $action = "/build";
1813     $action = "/clean" if $clean;
1814
1815     # Find Visual Studio installation.
1816     my $vsInstallDir;
1817     my $programFilesPath = $ENV{'PROGRAMFILES'} || "C:\\Program Files";
1818     if ($ENV{'VSINSTALLDIR'}) {
1819         $vsInstallDir = $ENV{'VSINSTALLDIR'};
1820     } else {
1821         $vsInstallDir = "$programFilesPath/Microsoft Visual Studio 8";
1822     }
1823     $vsInstallDir = `cygpath "$vsInstallDir"` if isCygwin();
1824     chomp $vsInstallDir;
1825     $vcBuildPath = "$vsInstallDir/Common7/IDE/devenv.com";
1826     if (! -e $vcBuildPath) {
1827         # Visual Studio not found, try VC++ Express
1828         $vcBuildPath = "$vsInstallDir/Common7/IDE/VCExpress.exe";
1829         if (! -e $vcBuildPath) {
1830             print "*************************************************************\n";
1831             print "Cannot find '$vcBuildPath'\n";
1832             print "Please execute the file 'vcvars32.bat' from\n";
1833             print "'$programFilesPath\\Microsoft Visual Studio 8\\VC\\bin\\'\n";
1834             print "to setup the necessary environment variables.\n";
1835             print "*************************************************************\n";
1836             die;
1837         }
1838     }
1839
1840     # Create command line and execute it.
1841     my @command = ($vcBuildPath, $projectPath, $action, $config);
1842     print "Building results into: ", baseProductDir(), "\n";
1843     print join(" ", @command), "\n";
1844     return system @command;
1845 }
1846
1847 sub buildChromium($@)
1848 {
1849     my ($clean, @options) = @_;
1850
1851     # We might need to update DEPS or re-run GYP if things have changed.
1852     if (checkForArgumentAndRemoveFromArrayRef("--update-chromium", \@options)) {
1853         system("perl", "Tools/Scripts/update-webkit-chromium") == 0 or die $!;
1854     }
1855
1856     my $result = 1;
1857     if (isDarwin()) {
1858         # Mac build - builds the root xcode project.
1859         $result = buildXCodeProject("Source/WebKit/chromium/WebKit", $clean, "-configuration", configuration(), @options);
1860     } elsif (isCygwin() || isWindows()) {
1861         # Windows build - builds the root visual studio solution.
1862         $result = buildChromiumVisualStudioProject("Source/WebKit/chromium/WebKit.sln", $clean);
1863     } elsif (isLinux()) {
1864         # Linux build - build using make.
1865         $ result = buildChromiumMakefile("all", $clean);
1866     } else {
1867         print STDERR "This platform is not supported by chromium.\n";
1868     }
1869     return $result;
1870 }
1871
1872 sub appleApplicationSupportPath
1873 {
1874     open INSTALL_DIR, "</proc/registry/HKEY_LOCAL_MACHINE/SOFTWARE/Apple\ Inc./Apple\ Application\ Support/InstallDir";
1875     my $path = <INSTALL_DIR>;
1876     $path =~ s/[\r\n\x00].*//;
1877     close INSTALL_DIR;
1878
1879     my $unixPath = `cygpath -u '$path'`;
1880     chomp $unixPath;
1881     return $unixPath;
1882 }
1883
1884 sub setPathForRunningWebKitApp
1885 {
1886     my ($env) = @_;
1887
1888     if (isAppleWinWebKit()) {
1889         $env->{PATH} = join(':', productDir(), dirname(installedSafariPath()), appleApplicationSupportPath(), $env->{PATH} || "");
1890     } elsif (isQt()) {
1891         my $qtLibs = `$qmakebin -query QT_INSTALL_LIBS`;
1892         $qtLibs =~ s/[\n|\r]$//g;
1893         $env->{PATH} = join(';', $qtLibs, productDir() . "/lib", $env->{PATH} || "");
1894     }
1895 }
1896
1897 sub runSafari
1898 {
1899     my ($debugger) = @_;
1900
1901     if (isAppleMacWebKit()) {
1902         return system "$FindBin::Bin/gdb-safari", argumentsForConfiguration() if $debugger;
1903
1904         my $productDir = productDir();
1905         print "Starting Safari with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n";
1906         $ENV{DYLD_FRAMEWORK_PATH} = $productDir;
1907         $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES";
1908         if (!isTiger() && architecture()) {
1909             return system "arch", "-" . architecture(), safariPath(), @ARGV;
1910         } else {
1911             return system safariPath(), @ARGV;
1912         }
1913     }
1914
1915     if (isAppleWinWebKit()) {
1916         my $result;
1917         my $productDir = productDir();
1918         if ($debugger) {
1919             setupCygwinEnv();
1920             chomp($ENV{WEBKITNIGHTLY} = `cygpath -wa "$productDir"`);
1921             my $safariPath = safariPath();
1922             chomp($safariPath = `cygpath -wa "$safariPath"`);
1923             $result = system $vcBuildPath, "/debugexe", "\"$safariPath\"", @ARGV;
1924         } else {
1925             $result = system File::Spec->catfile(productDir(), "WebKit.exe"), @ARGV;
1926         }
1927         return $result if $result;
1928     }
1929
1930     return 1;
1931 }
1932
1933 sub runMiniBrowser
1934 {
1935     if (isAppleMacWebKit()) {
1936         my $productDir = productDir();
1937         print "Starting MiniBrowser with DYLD_FRAMEWORK_PATH set to point to $productDir.\n";
1938         $ENV{DYLD_FRAMEWORK_PATH} = $productDir;
1939         $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES";
1940         my $miniBrowserPath = "$productDir/MiniBrowser.app/Contents/MacOS/MiniBrowser";
1941         if (!isTiger() && architecture()) {
1942             return system "arch", "-" . architecture(), $miniBrowserPath, @ARGV;
1943         } else {
1944             return system $miniBrowserPath, @ARGV;
1945         }
1946     }
1947
1948     return 1;
1949 }
1950
1951 sub debugMiniBrowser
1952 {
1953     if (isAppleMacWebKit()) {
1954         my $gdbPath = "/usr/bin/gdb";
1955         die "Can't find gdb executable. Is gdb installed?\n" unless -x $gdbPath;
1956
1957         my $productDir = productDir();
1958
1959         $ENV{DYLD_FRAMEWORK_PATH} = $productDir;
1960         $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = 'YES';
1961
1962         my $miniBrowserPath = "$productDir/MiniBrowser.app/Contents/MacOS/MiniBrowser";
1963
1964         print "Starting MiniBrowser under gdb with DYLD_FRAMEWORK_PATH set to point to built WebKit2 in $productDir.\n";
1965         my @architectureFlags = ("-arch", architecture()) if !isTiger();
1966         exec $gdbPath, @architectureFlags, $miniBrowserPath or die;
1967         return;
1968     }
1969     
1970     return 1;
1971 }
1972
1973 sub runWebKitTestRunner
1974 {
1975     if (isAppleMacWebKit()) {
1976         my $productDir = productDir();
1977         print "Starting WebKitTestRunner with DYLD_FRAMEWORK_PATH set to point to $productDir.\n";
1978         $ENV{DYLD_FRAMEWORK_PATH} = $productDir;
1979         $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES";
1980         my $webKitTestRunnerPath = "$productDir/WebKitTestRunner";
1981         if (!isTiger() && architecture()) {
1982             return system "arch", "-" . architecture(), $webKitTestRunnerPath, @ARGV;
1983         } else {
1984             return system $webKitTestRunnerPath, @ARGV;
1985         }
1986     }
1987
1988     return 1;
1989 }
1990
1991 sub debugWebKitTestRunner
1992 {
1993     if (isAppleMacWebKit()) {
1994         my $gdbPath = "/usr/bin/gdb";
1995         die "Can't find gdb executable. Is gdb installed?\n" unless -x $gdbPath;
1996
1997         my $productDir = productDir();
1998         $ENV{DYLD_FRAMEWORK_PATH} = $productDir;
1999         $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = 'YES';
2000
2001         my $webKitTestRunnerPath = "$productDir/WebKitTestRunner";
2002
2003         print "Starting WebKitTestRunner under gdb with DYLD_FRAMEWORK_PATH set to point to $productDir.\n";
2004         my @architectureFlags = ("-arch", architecture()) if !isTiger();
2005         exec $gdbPath, @architectureFlags, $webKitTestRunnerPath or die;
2006         return;
2007     }
2008
2009     return 1;
2010 }
2011
2012 sub runTestWebKitAPI
2013 {
2014     if (isAppleMacWebKit()) {
2015         my $productDir = productDir();
2016         print "Starting TestWebKitAPI with DYLD_FRAMEWORK_PATH set to point to $productDir.\n";
2017         $ENV{DYLD_FRAMEWORK_PATH} = $productDir;
2018         $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES";
2019         my $testWebKitAPIPath = "$productDir/TestWebKitAPI";
2020         if (!isTiger() && architecture()) {
2021             return system "arch", "-" . architecture(), $testWebKitAPIPath, @ARGV;
2022         } else {
2023             return system $testWebKitAPIPath, @ARGV;
2024         }
2025     }
2026
2027     return 1;
2028 }
2029
2030 1;