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